package com.wty.basic.IoDemo;

import ch.qos.logback.core.net.SyslogOutputStream;
import org.junit.Test;

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 *
 * 压缩文件的测试
 * @Author wangtengyu
 * @Create 2018-08-10-16:21
 */
public class ZipDemo {


    //压缩一个文件
    @Test
    public void test1() throws IOException {
        //定义要压缩的文件
        File srcFile = new File("src/main/resources/zipTest.txt");
        //定义压缩文件名称
        File zipFile = new File("src/main/resources/wtyZip.zip");
        zOut(srcFile, zipFile);


    }

    //压缩一个文件夹(文件夹里只有文件)
    @Test
    public void test2() throws IOException {
        //定义源路径
        File srcFile = new File("src/main/resources/dirtest");
        //定义压缩文件名称
        File zipFile = new File("src/main/resources/dirtest.zip");
        zOut(srcFile, zipFile);
    }

    //压缩一个文件夹(文件夹里有文件和文件夹)
    @Test
    public void test3() throws IOException {
        //定义源路径
        File srcFile = new File("src/main/resources/dirtest2");
        //定义压缩文件名称
        File zipFile = new File("src/main/resources/dirtest2.zip");
        zOut(srcFile, zipFile);
    }

    /**
     *
     * @param srcFile 源地址 这里的源地址，是最源头的，要一层层的拼接下去
     * @param zipFile 压缩文件地址
     * @throws IOException
     */
    //根据指定路径，将路径下文件及文件夹压缩的方法
    private void zOut(File srcFile, File zipFile) throws IOException {
        //先判断源地址是否失效
        if (!srcFile.exists()) {
            throw new RuntimeException("源地址失效");
        }
        //定义输出流
        ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(zipFile));//文件不存在时会创建文件
        //是文件夹
        if (srcFile.isDirectory()) {
            //遍历文件夹，获得每一个输入流
            File fileList[] = srcFile.listFiles();
            for (File f : fileList) {//定义输入流
                if (f.isDirectory()) {
                    //压缩的输出流是同一个流，不要打开多个流，容易造成读写的错误

                    //拼接根文件夹路径传给下一级
                    String rootPath=srcFile.getName();
                    zOut(f, zipFile, zout,rootPath);
                } else {
                    ZipEntry zipEntry = new ZipEntry(srcFile.getName() + File.separator + f.getName());
                    zip(f,zipEntry,zout);
                }
            }
        } else {//是文件
            ZipEntry zipEntry = new ZipEntry(srcFile.getName());
            zip(srcFile,zipEntry,zout);
        }
        zout.close();
    }

    /**
     * 走到这个方法肯定就是文件夹了
     * @param srcFile   源头地址
     * @param zipFile   目标地址
     * @param zout      同一个流
     * @param rootPath  上级文件夹路径，用于拼接压缩后的文件路径
     * @throws IOException
     */
    private void zOut(File srcFile, File zipFile, ZipOutputStream zout,String rootPath) throws IOException {
        //先判断源地址是否失效
        if (!srcFile.exists()) {
            throw new RuntimeException("源地址失效");
        }
        //遍历文件夹，获得每一个输入流
        File fileList[] = srcFile.listFiles();
        rootPath=rootPath+File.separator+srcFile.getName();
        for (File f : fileList) {//定义输入流
            if (f.isDirectory()) {
                zOut(f, zipFile,zout,rootPath);
            } else {
                ZipEntry zipEntry = new ZipEntry(rootPath+File.separator+f.getName());
                zip(f,zipEntry,zout);
            }
        }

    }

    //实际压缩的方法
    private void zip(File f,ZipEntry zipEntry,ZipOutputStream zout) throws IOException {
        FileInputStream input = new FileInputStream(f);
        zout.putNextEntry(zipEntry);
        byte b[] = new byte[1024];
        int len = -1;
        while ((len = input.read(b)) != -1) {
            zout.write(b, 0, len);
        }
        input.close();
    }


}
